import { BillCodeGenerator } from './../service/tool.service';
import {
  Body,
  Controller,
  Del,
  Get,
  Inject,
  Param,
  Post,
  Put,
} from '@midwayjs/core';
import {
  LeaveApplyQueryCondition,
  LeaveAuditQueryCondition,
  LeaveBill,
  LeaveBillAuditDto,
  LeaveBillInsertDto,
  LeaveBillState,
} from './../entity/leave.entity';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { Context } from '@midwayjs/koa';
import { BillStateError, MissTargetError } from '../filter/error.filter';
@Controller('/leave')
export class LeaveBillController {
  @InjectEntityModel(LeaveBill)
  repo: Repository<LeaveBill>;
  @Inject()
  billCodeGenerator: BillCodeGenerator;
  @Inject()
  ctx: Context;
  //   新增 暂存新增 无->toSubmit
  @Post('/insert')
  async insert(@Body() leaveBillInsertDto: LeaveBillInsertDto) {
    console.log('新增请假信息:' + leaveBillInsertDto);
    const leaveBill = new LeaveBill();
    // 前端指定的四个字段 请假原因 请假时间等
    Object.assign(leaveBill, leaveBillInsertDto);
    // 后端指定的四个字段 表单状态 流水号 等
    leaveBill.billState = LeaveBillState.toSubmit;
    leaveBill.leaveBillCode = await this.billCodeGenerator.nextCode('QJ');
    leaveBill.applier = this.ctx.getAttr('username');
    leaveBill.modifyTime = new Date();
    return await this.repo.save(leaveBill);
  }
  @Post('/insert2')
  async insert2(@Body() leaveBill: LeaveBill) {
    leaveBill.billState = LeaveBillState.toSubmit;

    leaveBill.leaveBillCode = await this.billCodeGenerator.nextCode('QJ');
    leaveBill.applier = this.ctx.getAttr('username');
    leaveBill.modifyTime = new Date();
    // 置空操作可选可不选
    leaveBill.applyTime = null;
    leaveBill.auditor = null;
    leaveBill.auditTime = null;

    return await this.repo.save(leaveBill);
  }

  //   修改 暂存 toSubmit->toSubmit
  @Put('/modify/:code')
  async modify(
    @Param('code') code: string,
    @Body() leaveBillInsertDto: LeaveBillInsertDto
  ) {
    const leaveBill = await this.repo.findOneBy({
      leaveBillCode: code,
    });
    if (!leaveBill) {
      throw new MissTargetError('待修改的数据不存在');
    }
    // 状态转变 toSubmit->toSubmit
    if (leaveBill.billState !== LeaveBillState.toSubmit) {
      throw new BillStateError('只有处于待提交状态的请假条才能修改');
    }
    leaveBill.billState = LeaveBillState.toSubmit;
    // 一般可以省略身份信息校验
    Object.assign(leaveBill, leaveBillInsertDto);
    leaveBill.modifyTime = new Date();
    return await this.repo.save(leaveBill);
  }
  //   提交 toSubmit -> toAudit
  @Put('/submit/:code')
  async submit(@Param('code') code: string) {
    // select * from LeaveBill l where l.leaveBillCode = code
    const leaveBill = await this.repo.findOneBy({
      leaveBillCode: code,
    });
    if (!leaveBill) {
      throw new MissTargetError('待提交的数据不存在');
    }
    // toSubmit -> toAudit
    // 从A状态转移到B状态 第一步就是确保自己在A状态
    if (leaveBill.billState !== LeaveBillState.toSubmit) {
      throw new BillStateError('只有处于待提交状态的请假条才能提交');
    }
    leaveBill.billState = LeaveBillState.toAudit;
    // 状态转换的后置操作 、事件 观察者
    leaveBill.auditor = 'zhaoliu008';
    leaveBill.applyTime = new Date();
    leaveBill.modifyTime = new Date();
    return await this.repo.save(leaveBill);
  }
  // query4applier
  /* select * from LeaveBill l
where l.leaveType in ( 'sick','annual')
and l.billState in ('toSubmit','toAudit')
and l.applier = 'swagger'
order by l.modifyTime desc
limit 0,2 */
  @Post('/query/applier')
  async query4applier(
    @Body() leaveApplyQueryCondition: LeaveApplyQueryCondition
  ) {
    const { pageNum, pageSize, leaveBillStates, leaveTypes } =
      leaveApplyQueryCondition;
    const pageStart = (pageNum - 1) * pageSize;
    const builder = this.repo.createQueryBuilder('l');
    const currentUser = this.ctx.getAttr('username');
    // console.log('leave types  ', leaveTypes);
    // 静态条件
    builder.andWhere('l.applier = :a', { a: currentUser });
    // 动态条件
    if (leaveTypes.length > 0) {
      builder.andWhere('l.leaveType in (:...t)', { t: leaveTypes });
    }
    if (leaveBillStates.length > 0) {
      builder.andWhere('l.billState in (:...y)', { y: leaveBillStates });
    }
    builder.orderBy('l.modifyTime', 'DESC');
    builder.offset(pageStart).limit(pageSize);
    const r = await builder.printSql().getManyAndCount();
    return {
      results: r[0],
      total: r[1],
    };
  }

  // 申请人 和 审核人 单独查看
  @Get('/find/:code')
  // 一般可以省略身份信息校验
  async findByCode(@Param('code') code: string) {
    const leaveBill = await this.repo.findOneBy({
      leaveBillCode: code,
    });
    if (!leaveBill) {
      throw new MissTargetError('待查看的请假单不存在');
    }
    return leaveBill;
  }

  // 单独删除 申请人
  @Del('/remove/:code')
  async removeByCode(@Param('code') code: string) {
    const leaveBill = await this.repo.findOneBy({
      leaveBillCode: code,
    });
    if (!leaveBill) {
      throw new MissTargetError('待删除的请假单不存在');
    }
    if (leaveBill.billState !== LeaveBillState.toSubmit) {
      throw new BillStateError('只有处于待提交状态的单据才能删除');
    }
    await this.repo.remove(leaveBill);
    return code;
  }

  // query4auditor
  /* select *
  from LeaveBill l
  where l.auditor = 'zhaoliu008'
  and l.applier like '%zhangsan001%'
  and l.leaveType in ('sick', 'annual')
  order by l.billState desc, l.modifyTime desc
  limit 2,2
   */
  @Post('/query/auditor')
  async query4auditor(
    @Body() leaveAuditQueryCondition: LeaveAuditQueryCondition
  ) {
    const { pageNum, pageSize, leaveTypes, applier } = leaveAuditQueryCondition;
    const pageStart = (pageNum - 1) * pageSize;
    const builder = this.repo.createQueryBuilder('l');
    const currentUser = this.ctx.getAttr('username');
    // 静态条件
    builder.andWhere('l.auditor = :a', { a: currentUser });
    // 动态条件
    if (applier) {
      builder.andWhere('l.applier like :apl', { apl: '%' + applier + '%' });
    }
    if (leaveTypes.length > 0) {
      builder.andWhere('l.leaveType in (:...t)', { t: leaveTypes });
    }
    builder.orderBy({
      'l.billState': 'ASC',
      'l.modifyTime': 'DESC',
    });
    builder.offset(pageStart).limit(pageSize);
    const r = await builder.printSql().getManyAndCount();
    return {
      results: r[0],
      total: r[1],
    };
  }
  //   {auditWord:"注意安全"}
  @Put('/audit/:code')
  async auditByCode(
    @Param('code') code: string,
    @Body() dto: LeaveBillAuditDto
  ) {
    const leaveBill = await this.repo.findOneBy({
      leaveBillCode: code,
    });
    if (!leaveBill) {
      throw new MissTargetError('待审核的请假单已不存在');
    }
    // 单据状态转化  toAudit => auditted
    if (leaveBill.billState !== LeaveBillState.toAudit) {
      throw new BillStateError('只有处于待审核状态的单据才能审核');
    }
    leaveBill.billState = LeaveBillState.Auditted;
    // 后置操作
    leaveBill.auditTime = new Date();
    leaveBill.auditWord = dto.auditWord;
    leaveBill.modifyTime = new Date();
    return await this.repo.save(leaveBill);
  }
  @Put('/resent/:code')
  async resentByCode(@Param('code') code: string) {
    const leaveBill = await this.repo.findOneBy({
      leaveBillCode: code,
    });
    if (!leaveBill) {
      throw new MissTargetError('待重交的请假单已不存在');
    }
    // 重交  toAudit => toSubmit
    if (leaveBill.billState !== LeaveBillState.toAudit) {
      throw new BillStateError('已审核的请假条不能打回重交');
    }
    leaveBill.billState = LeaveBillState.toSubmit;
    // 后置操作
    leaveBill.resentTimes++;
    leaveBill.modifyTime = new Date();
    leaveBill.applyTime = null;
    leaveBill.auditor = null;
    return await this.repo.save(leaveBill);
  }
}
